<?php

/*
    fieldtypes.formgenerator.php

    This script is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This script is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this script. If not, see <http://www.gnu.org/licenses/>.

    http://www.truefusion.org/
*/

/**
 *	\file fieldtypes.formgenerator.php
 *	\brief TFCMS Field Types classes
 */

abstract class InputField
	{
		private $class; ///< Stores the HTML class attribute value.
		private $disabled = false; ///< Stores whether or not this field should be disabled.
		private $errors = array(); ///< Stores all the errors from validation.
		private $fieldSize = 20; ///< Stores the HTML size attribute value.
		private $filter; ///< Stores the regular expression pattern for later use.
		private $functions = array(); ///< An array of function names to be applied to the field data.
		private $id; ///< Stores the HTML id attribute value. Required when using a label.
		private $label; ///< Stores the text for the HTML element label.
		private $maxLength = 0; ///< Stores the HTML maxlength attribute value.
		private $name; ///< Stores the HTML name attribute value. \warning All names must be unique unless using checkboxes or radioes.
		private $numbersOnly = false; ///< Stores whether or not the field should consist of only numbers.
		private $readOnly = false; ///< Stores the HTML readonly attribute value.
		private $required = true; ///< Stores whether or not field requires input.
		private $showRequired = true; ///< Stores whether or not to render the HTML 5 attribute, required.
		private $styleSheet; ///< Stores the HTML style attribute value.
		private $type; ///< Stores the HTML type attribute value.
		private $value; ///< Stores the HTML value attribute value.

		static $AvailableTypes = array("button",
									  "checkbox",
									  "file",
									  "hidden",
									  "image",
									  "password",
									  "radio",
									  "reset",
									  "select",
									  "submit",
									  "text",
									  "textfield");

		function __construct($name)
			{
				$this->name = $name;
			}

		function getApplicableFilters()
			{
				return $this->functions;
			}

		function applyApplicableFilters()
			{
				$value = $this->getValue();
				foreach ($this->getApplicableFilters() as $function)
				{
					if (function_exists($function))
						$value = $function($value);
				}
				$this->setValue($value);
			}

		/*!	\brief Add function names to later be called.
		 *
		 *	\note In order for the functions listed to work, you can
		 *		only add functions that take in only one parameter, the
		 *		value of the field itself, and return the modified
		 *		value.
		 *
		 *	@see applyApplicableFilters()
		 */
		function addApplicableFilters()
			{
				foreach (func_get_args() as $function)
					$this->functions[] = $function;
			}

		function getClass()
			{
				return $this->class;
			}

		function setClass($class)
			{
				$this->class = (string) $class;
			}

		function isDisabled()
			{
				return (bool) $this->disabled;
			}

		function setDisabled($yes)
			{
				$this->disabled = (bool) $yes;
			}

		function getFieldSize()
			{
				return (int) $this->fieldSize;
			}

		function setFieldSize($size)
			{
				$this->fieldSize = (int) $size;
			}

		function getId()
			{
				return $this->id;
			}

		function setId($id)
			{
				$this->id = (string) $id;
			}

		function getLabel()
			{
				return $this->label;
			}

		/*! \brief Applies a label to the field.
		 *
		 *	\attention Must set an ID with setId() in order for this to
		 *	work.
		 *
		 *	@param string $label Text you want the label to show.
		 *	@see setId()
		 */
		function setLabel($label)
			{
				$this->label = (string) $label;
			}

		function getMaxLength()
			{
				return $this->maxLength;
			}

		function setMaxLength($max)
			{
				$this->maxLength = (int) $max;
			}

		function getName()
			{
				return $this->name;
			}

		/*! \return the name that would be present in the resulting PHP array keys of the form field.
		 */
		function getActualName()
		{
			if (substr($this->name, -2) == "[]")
				return substr($this->name, 0, -2);
			else
				return $this->name;
		}

		function setName($name)
			{
				$this->name = (string) $name;
			}

		function isNumbersOnly()
			{
				return (bool) $this->numbersOnly;
			}

		function setNumbersOnly($yes)
			{
				$this->numbersOnly = (bool) $yes;
			}

		function isReadOnly()
			{
				return (bool) $this->readOnly;
			}

		/*!	\brief Set the field as read-only.
		 *
		 *	\attention Only proper for text and password fields.
		 *
		 *	@param bool $yes
		 *	@see isReadOnly()
		 */
		function setReadOnly($yes)
			{
				$this->readOnly = (bool) $yes;
			}

		function getRegexFilter()
			{
				return $this->filter;
			}

		function setRegexFilter($regex)
			{
				$this->filter = $regex;
			}

		function isRequired()
			{
				return (bool) $this->required;
			}

		function setRequired($yes)
			{
				$this->required = (bool) $yes;
			}

		/*! \brief Wanna-be "overloaded" function.
		 *
		 *	If a value is passed, store the value.
		 *
		 *	\return If no value is passed, returns whether or not (true or false) to show the HTML 5 attribute, required.
		 *
		 *	@param bool Only one parameter will be accepted.
		 */
		function showRequiredAttribute()
			{
				if (func_num_args() > 0)
					$this->showRequired = (bool) func_get_arg(0);
				else
					return $this->showRequired;
			}

		function getStyleSheet()
			{
				return $this->styleSheet;
			}

		/*! \brief Sets the stylesheet for the field.
		 *
		 *	@param string $css Whatever you want to go inside the HTML style attribute.
		 *	@see getStyleSheet()
		 */
		function setStyleSheet($css)
			{
				$this->styleSheet = (string) $css;
			}

		function getType()
			{
				return $this->type;
			}

		protected function setType($type)
			{
				$this->type = (string) $type;
			}

		function getValue()
			{
				return $this->value;
			}

		function setValue($value)
			{
				if (get_magic_quotes_gpc())
					$value = stripslashes($value);

				$this->value = (string) $value;
			}

		abstract function renderField();

		function renderLabel()
			{
				if ($this->getLabel())
					echo "<label for=\"".$this->getId()."\">".$this->getLabel()."</label>\n";
			}

		/*! \brief Checks to see if the field's data is correct.
		 *
		 *	\return \em true if validation passed; \em false if it failed.
		 */
		abstract function verifyData();

		/*! \brief Verify that the value is not greater than maximum length.
		 *
		 *	\return \em true if greater than; \em false if within limits.
		 *
		 *	@see getValue()
		 */
		abstract function verifyLength();

		function getErrors()
			{
				return $this->errors;
			}

		function hasErrors()
			{
				return (bool) (count($this->errors) > 0);
			}

		function storeError($error)
			{
				$this->errors[] = $error;
				return 1;
			}
	}

class TextInput extends InputField
	{
		/*!	\class TextInput
		 *	\brief TextInput constructor
		 *
		 *	Instantiates a TextInput object.
		 */
		function __construct($name)
			{
				parent::__construct($name);
				$this->setType("text");
			}

		function renderField()
			{
				echo "<input type=\"".$this->getType()."\" ";

				if ($this->getName())
					echo "name=\"".$this->getName()."\" ";

				if ($this->getStyleSheet())
					echo "style=\"".$this->getStyleSheet()."\" ";

				if ($this->getClass())
					echo "class=\"".$this->getClass()."\" ";

				if ($this->getId())
					echo "id=\"".$this->getId()."\" ";

				if ($this->getFieldSize() > 0)
					echo "size=\"".$this->getFieldSize()."\" ";

				if ($this->getValue())
					echo "value=\"".$this->getValue()."\" ";

				if ($this->getMaxLength() > 0)
					echo "maxlength=\"".$this->getMaxLength()."\" ";

				if ($this->isReadOnly())
					echo "readonly=\"readonly\" ";

				if ($this->isRequired()
					&& $this->showRequiredAttribute())
						echo "required=\"required\" ";

				echo "/>\n";
			}

		function verifyData()
			{
				$this->applyApplicableFilters();

				if ($this->isRequired()
					&& $this->getValue() == "")
						$this->storeError("This field is required.");

				else if ($this->getValue() != "")
				{
					if ($this->isNumbersOnly()
						&& preg_match("/\D+/", $this->getValue()))
							$this->storeError("Must consist of numbers only.");

					if ($this->getRegexFilter() != ""
						&& !preg_match($this->getRegexFilter(), $this->getValue()))
							$this->storeError("The data provided is invalid.");

					if ($this->getMaxLength() > 0
						&& strlen($this->getValue()) > $this->getMaxLength())
							$this->storeError("The data provided is longer than ".$this->getMaxLength()." characters.");
				}

				return ($this->hasErrors()) ? false : true;
			}

		function verifyLength()
			{
				return (bool) (strlen($this->getValue()) > $this->getMaxLength());
			}
	}

class HiddenInput extends TextInput
	{
		function __construct($name)
			{
				parent::__construct($name);
				$this->setType("hidden");
			}

		function renderField()
			{
				echo "<input type=\"".$this->getType()."\" ";

				if ($this->getName())
					echo "name=\"".$this->getName()."\" ";

				if ($this->getId())
					echo "id=\"".$this->getId()."\" ";

				if ($this->getValue())
					echo "value=\"".$this->getValue()."\" ";

				echo "/>\n";
			}

		function verifyData()
			{
				return (bool) ($_POST[$this->getName()] == $this->getValue());
			}

		function verifyLength()
			{
				return false;
			}
	}

class PasswordInput extends TextInput
	{
		function __construct($name)
			{
				parent::__construct($name);
				$this->setType("password");
			}
	}

class CheckBoxInput extends InputField
	{
		private $checked;

		function __construct($name)
			{
				parent::__construct($name);
				$this->setType("checkbox");
			}

		function isChecked()
			{
				return (bool) $this->checked;
			}

		function setChecked($yes)
			{
				$this->checked = (bool) $yes;
			}

		function renderField()
			{
				echo "<input type=\"".$this->getType()."\" ";

				if ($this->getName())
					echo "name=\"".$this->getName()."\" ";

				if ($this->getStyleSheet())
					echo "style=\"".$this->getStyleSheet()."\" ";

				if ($this->getClass())
					echo "class=\"".$this->getClass()."\" ";

				if ($this->getId())
					echo "id=\"".$this->getId()."\" ";

				if ($this->getValue())
					echo "value=\"".$this->getValue()."\" ";

				if ($this->isChecked())
					echo "checked=\"checked\" ";

				echo "/>\n";

				$this->renderLabel();
			}

		function verifyData()
			{
			}

		function verifyLength()
			{
				return false;
			}
	}

class RadioButtonInput extends CheckBoxInput
	{
		function __construct($name)
			{
				parent::__construct($name);
				$this->setType("radio");
			}
	}

class ButtonInput extends InputField
	{
		function __construct($name)
			{
				parent::__construct($name);
				$this->setRequired(false);
				$this->setType("button");
			}

		function renderField()
			{
				echo "<input type=\"".$this->getType()."\" ";

				if ($this->getName())
					echo "name=\"".$this->getName()."\" ";

				if ($this->getStyleSheet())
					echo "style=\"".$this->getStyleSheet()."\" ";

				if ($this->getClass())
					echo "class=\"".$this->getClass()."\" ";

				if ($this->getId())
					echo"id=\"".$this->getId()."\" ";

				if ($this->getValue())
					echo "value=\"".$this->getValue()."\" ";

				echo "/>\n";
			}

		function verifyData()
			{
				return true;
			}

		function verifyLength()
			{
				return false;
			}
	}

class SubmitButtonInput extends ButtonInput
	{
		function __construct($name = "SubmitBtn")
			{
				parent::__construct($name);
				$this->setType("submit");
				$this->setValue("Submit Form");
			}
	}

class ResetButtonInput extends ButtonInput
	{
		function __construct($name = "ResetBtn")
			{
				parent::__construct($name);
				$this->setType("reset");
				$this->setValue("Clear Form");
			}
	}

class ImageButtonInput extends ButtonInput
	{
		private $alt;
		private $imageSrc;

		function __construct($name, $image_src = NULL)
			{
				parent::__construct($name);
				$this->setImageSrc($image_src);
				$this->setType("image");
			}

		function getAlternativeText()
			{
				return $this->alt;
			}

		function setAlternativeText($text)
			{
				$this->alt = $text;
			}

		function getImageSrc()
			{
				return $this->imageSrc;
			}

		function setImageSrc($src)
			{
				$this->imageSrc = (string) $src;
			}

		function renderField()
			{
				echo "<input type=\"".$this->getType()."\" ";

				if ($this->getName())
					echo "name=\"".$this->getName()."\" ";

				if ($this->getImageSrc())
					echo "src=\"".$this->getImageSrc()."\" ";

				if ($this->getAlternativeText())
					echo "alt=\"".$this->getAlternativeText()."\" ";

				if ($this->getStyleSheet())
					echo "style=\"".$this->getStyleSheet()."\" ";

				if ($this->getClass())
					echo "class=\"".$this->getClass()."\" ";

				if ($this->getId())
					echo "id=\"".$this->getId()."\" ";

				if ($this->getValue())
					echo "value=\"".$this->getValue()."\" ";

				echo "/>\n";
			}
	}

class FileInput extends TextInput
	{
		private $mimeType;

		function __construct($name)
			{
				parent::__construct($name);
				$this->setType("file");
			}

		function getMimeType()
			{
				return $this->mimeType;
			}

		function setMimeType($mimeType)
			{
				$this->mimeType = $mimeType;
			}

		function renderField()
			{
				echo "<input type=\"".$this->getType()."\" ";

				if ($this->getName())
					echo "name=\"".$this->getName()."\" ";

				if ($this->getStyleSheet())
					echo "style=\"".$this->getStyleSheet()."\" ";

				if ($this->getClass())
					echo "class=\"".$this->getClass()."\" ";

				if ($this->getId())
					echo "id=\"".$this->getId()."\" ";

				if ($this->getValue())
					echo "value=\"".$this->getValue()."\" ";

				if ($this->getMimeType())
					echo "accept=\"".$this->getMimeType()."\" ";

				echo "/>\n";
			}

		function verifyData()
			{
				if ($this->getValue() == ""
					&& $this->isRequired())
						$this->storeError("This field is required.");

				return ($this->hasErrors()) ? false : true;
			}

		function verifyLength()
			{
				return false;
			}
	}

class TextArea extends TextInput
	{
		private $rows = 15;
		private $cols = 60;

		function __construct($name)
			{
				parent::__construct($name);
			}

		function getColumns()
			{
				return $this->cols;
			}

		function setColumns($cols)
			{
				$this->cols = (int) $cols;
			}

		function getRows()
			{
				return $this->rows;
			}

		function setRows($rows)
			{
				$this->rows = (int) $rows;
			}

		function renderField()
			{
				echo "<textarea";

				if ($this->getName())
					echo " name=\"".$this->getName()."\"";

				if ($this->getRows() > 0)
					echo " rows=\"".$this->getRows()."\"";

				if ($this->getColumns() > 0)
					echo " cols=\"".$this->getColumns()."\"";

				if ($this->isReadOnly())
					echo " readonly=\"readonly\"";

				if ($this->isDisabled())
					echo " disabled=\"disabled\"";

				if ($this->getStyleSheet())
					echo " style=\"".$this->getStyleSheet()."\"";

				if ($this->getClass())
					echo " class=\"".$this->getClass()."\"";

				if ($this->getId())
					echo " id=\"".$this->getId()."\"";

				echo ">".$this->getValue()."</textarea>";
			}
	}

?>
